package com.easylinkin.linkappapi.space.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.analyze.mapper.AnalyzeDateSourceMapper;
import com.easylinkin.linkappapi.asset.mapper.AssetMapper;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelReadUtil;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.entity.DeviceRefAreaScope;
import com.easylinkin.linkappapi.device.entity.DeviceVoExt;
import com.easylinkin.linkappapi.device.mapper.DeviceMapper;
import com.easylinkin.linkappapi.device.service.DeviceRefAreaScopeService;
import com.easylinkin.linkappapi.function.entity.TenantFunctionRefArea;
import com.easylinkin.linkappapi.function.mapper.TenantFunctionRefAreaMapper;
import com.easylinkin.linkappapi.function.service.TenantFunctionRefAreaService;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionRoomMapper;
import com.easylinkin.linkappapi.ruleengine.mapper.RuleEngineMapper;
import com.easylinkin.linkappapi.security.constant.LinkappUserConstant;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.space.entity.LinkappArea;
import com.easylinkin.linkappapi.space.entity.LinkappSpace;
import com.easylinkin.linkappapi.space.mapper.LinkappAreaMapper;
import com.easylinkin.linkappapi.space.mapper.LinkappSpaceMapper;
import com.easylinkin.linkappapi.space.service.LinkappAreaService;
import com.easylinkin.linkappapi.space.service.LinkappSpaceService;
import com.easylinkin.linkappapi.space.vo.SpaceTreeVo;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.collection.CollectionUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.easylinkin.linkappapi.videomonitor.entity.DeviceVideoMonitorVo;
import com.easylinkin.linkappapi.videomonitor.service.DeviceVideoMonitorService;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p></p>
 *
 * @author liuming
 * @since 2020/4/14
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class LinkappAreaServiceImpl extends ServiceImpl<LinkappAreaMapper, LinkappArea> implements LinkappAreaService {

	private static final Logger LOGGER = LoggerFactory.getLogger(LinkappAreaServiceImpl.class);

    @Resource
    LinkappAreaMapper linkappAreaMapper;
    @Resource
    LinkappSpaceMapper linkappSpaceMapper;
    @Resource
    LinkappSpaceService linkappSpaceService;
    @Resource
    DeviceMapper deviceMapper;
    @Resource
    LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private DistributionRoomMapper distributionRoomMapper;
    @Resource
    private AnalyzeDateSourceMapper analyzeDateSourceMapper;
    @Resource
    private AssetMapper assetMapper;
    @Resource
    private RuleEngineMapper ruleEngineMapper;

    @Resource
    private TenantFunctionRefAreaMapper tenantFunctionRefAreaMapper;
    @Resource
    private TenantFunctionRefAreaService tenantFunctionRefAreaService;
    @Resource
    private DeviceRefAreaScopeService deviceRefAreaScopeService;
    @Resource
    private CommonService commonService;
    @Lazy
    @Autowired
    private DeviceVideoMonitorService videoMonitorService;

    @Override
    public boolean addLinkappArea(LinkappArea linkappArea) {
        LinkappUser user = linkappUserContextProducer.getCurrent();
        linkappArea.setCreateTime(new Date());
        linkappArea.setTenantId(user.getTenantId());
        commonService.setCreateAndModifyInfo(linkappArea);
        boolean save = save(linkappArea);
        return save;
    }


    @Override
    public String getReplacedNewAreaPath(String oldSpaceName, String newSpaceName) {
        String[] oldStrs = oldSpaceName.split("/");
        String[] newStrs = newSpaceName.split(":");
        for (int i = 0; i < oldStrs.length; i++) {
            if (i > newStrs.length - 1) {
                break;
            }
            if (!oldStrs[i].equals(newStrs[i])) {
                oldStrs[i] = newStrs[i];
                break;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < oldStrs.length; i++) {
            sb.append(oldStrs[i]).append("/");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    @Override
    @Transactional
    public boolean updateLinkappArea(LinkappArea linkappArea) {
//        if (linkappArea.getStatus().equals("0")) {
//            boolean updateById = this.updateById(linkappArea);
//            return updateById;
//        }

        LinkappArea linkappAreaTemp = new LinkappArea();
        linkappAreaTemp.setId(linkappArea.getId());

        List<LinkappArea> queryList = linkappAreaMapper.selectLinkappArea(linkappAreaTemp);
        linkappAreaTemp = queryList.size() > 0 ? queryList.get(0) : null;
//        linkappAreaTemp = linkappAreaMapper.selectLinkappArea(linkappAreaTemp);
        boolean updateById = false;
        //同步更新区域中的对应areaPath
        LinkappArea linkappAreaQuery = new LinkappArea();
        linkappAreaQuery.setId(linkappArea.getId());
        List<LinkappArea> areaList = linkappAreaMapper.selectLinkappAreaLowLevlNodeList(linkappAreaQuery);

        for (LinkappArea linkappAreaNew : areaList) {
            if (!linkappArea.getId().equals(linkappAreaNew.getId())) {
                String areaPath = getReplacedNewAreaPath(linkappAreaNew.getAreaPath(), linkappArea.getAreaPath());
                linkappAreaNew.setAreaPath(areaPath);
                commonService.setModifyInfo(linkappAreaNew);
                linkappAreaMapper.updateById(linkappAreaNew);
            } else {
                commonService.setModifyInfo(linkappArea);
                updateById = this.updateById(linkappArea);
            }

        }

        //同步更新设备表中的areaPath
        Device deviceQuery = new Device();
        //:替换/
        deviceQuery.setAreaPath(linkappAreaTemp.getAreaPath().replaceAll(":","/"));
        List<Device> deviceList = deviceMapper.selectDevicesByAreaPath(deviceQuery);
        for (Device device : deviceList) {
//            String deviceAreaPath = device.getAreaPath().replaceAll(linkappAreaTemp.getAreaPath(), linkappArea.getAreaPath());
            String deviceAreaPath = getReplacedNewAreaPath(device.getAreaPath(), linkappArea.getAreaPath());
            device.setAreaPath(deviceAreaPath);
            deviceMapper.updateById(device);
        }
        //同步更新租户区域绑定
        QueryWrapper<TenantFunctionRefArea> tenantFunctionRefAreaQueryWrapper = new QueryWrapper<>();
        tenantFunctionRefAreaQueryWrapper.likeRight("area_path",linkappAreaTemp.getAreaPath()+":").or()
                .eq("area_path",linkappAreaTemp.getAreaPath());
        List<TenantFunctionRefArea> tenantFunctionRefAreas = tenantFunctionRefAreaService.list(tenantFunctionRefAreaQueryWrapper);
        for (TenantFunctionRefArea tenantFunctionRefArea : tenantFunctionRefAreas) {
            String deviceAreaPath = getReplacedNewAreaPath(tenantFunctionRefArea.getAreaPath(), linkappArea.getAreaPath());
            tenantFunctionRefArea.setAreaPath(deviceAreaPath);
            UpdateWrapper updateWrapper=new UpdateWrapper();
            updateWrapper.set("area_path",deviceAreaPath);
            updateWrapper.eq("area_id",tenantFunctionRefArea.getAreaId());
            tenantFunctionRefAreaService.update(updateWrapper);
        }
        //同步更新设备绑定表
        QueryWrapper<DeviceRefAreaScope> deviceRefAreaScopeQueryWrapper = new QueryWrapper<>();
        deviceRefAreaScopeQueryWrapper.likeRight("area_path",linkappAreaTemp.getAreaPath().replaceAll(":","/")+"/").or()
                .eq("area_path",linkappAreaTemp.getAreaPath());
        List<DeviceRefAreaScope> deviceRefAreaScopes = deviceRefAreaScopeService.list(deviceRefAreaScopeQueryWrapper);
        for (DeviceRefAreaScope deviceRefAreaScope : deviceRefAreaScopes) {
            String deviceAreaPath = getReplacedNewAreaPath(deviceRefAreaScope.getAreaPath(), linkappArea.getAreaPath());
            deviceRefAreaScope.setAreaPath(deviceAreaPath);
            UpdateWrapper updateWrapper=new UpdateWrapper();
            updateWrapper.set("area_path",deviceAreaPath);
            updateWrapper.eq("area_id",deviceRefAreaScope.getAreaId());
            deviceRefAreaScopeService.update(updateWrapper);
        }


        return updateById;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteLinkappAreaList(Set<String> ids) {
        QueryWrapper qw = new QueryWrapper();
        qw.in("area_id", ids);
// 检查空间对应的默认创建的区域是否被其他的业务模块用到
        Assert.isTrue(distributionRoomMapper.selectCount(qw) == 0, "对应区域被 配电房 用到");
        Assert.isTrue(analyzeDateSourceMapper.selectCount(qw) == 0, "对应区域被 数据分析 用到");
        Assert.isTrue(deviceMapper.selectCount(qw) == 0, "对应区域被 设备 用到");
        Assert.isTrue(ruleEngineMapper.selectCount(qw) == 0, "对应区域被 规则引擎 用到");
        qw = new QueryWrapper();
        qw.in("asset_area_id", ids);
        Assert.isTrue(assetMapper.selectCount(qw) == 0, "对应区域被 资产 用到");
        return removeByIds(ids);
    }

    @Override
    public List<LinkappArea> selectLinkappAreaList(LinkappArea linkappArea) {
        return linkappAreaMapper.selectLinkappAreaList(linkappArea);
    }

    @Override
    public List<SpaceTreeVo> selectMostChildAreaList(LinkappArea linkappArea) {
        List<SpaceTreeVo> stvList = selectLinkappAreaTreeList(linkappArea);
        setMostChildFlag(stvList);
        return stvList;
    }

    @Override
    public void setMostChildFlag(List<SpaceTreeVo> stvList) {
        List<String> areaPathList = stvList.stream().map(SpaceTreeVo::getAreaPath).collect(Collectors.toList());
        for (SpaceTreeVo stv:
                stvList) {
            List<String> containsList = search(stv.getAreaPath(), areaPathList);
            if(containsList != null && containsList.size() == 1){
                stv.setMostChildFlag(true);
            }
        }
    }

    public List<String> search(String areaPath,List<String> list){
        List results = new ArrayList();
        Pattern pattern = Pattern.compile(areaPath);
        for(int i=0; i < list.size(); i++){
            Matcher matcher = pattern.matcher(list.get(i));
            if(matcher.find()){
                results.add(list.get(i));
            }
        }
        return results;
    }

    @Override
    public List<LinkappArea> selectAreaListByTenantId(LinkappArea linkappArea) {
        return linkappAreaMapper.selectAreaListByTenantId(linkappArea);
    }

    @Override
    public LinkappArea selectLinkappArea(LinkappArea linkappArea) {
        List<LinkappArea> queryList = linkappAreaMapper.selectLinkappArea(linkappArea);
        return queryList.size() > 0 ? queryList.get(0) : null;
    }

    @Override
    public List<SpaceTreeVo> selectLinkappAreaTreeList(LinkappArea linkappArea) {
        LinkappUser user = linkappUserContextProducer.getCurrent();
        if (LinkappUserConstant.ADMIN_TYPE.equals(user.getType())) {
            return linkappAreaMapper.selectLinkappAreaTreeList(linkappArea);
        } else {
            List<LinkappSpace> spaceList = linkappSpaceMapper.selectLinkappSpaceByUser(user.getId().toString());
            List<String> spaces = new ArrayList<String>();
            if (spaceList.isEmpty()) {
                spaces.add("-1");
                linkappArea.setSpaceIds(spaces);
            } else {
                for (LinkappSpace space : spaceList) {
                    spaces.add(space.getId());
                }
                linkappArea.setSpaceIds(spaces);
            }
            return linkappAreaMapper.selectLinkappAreaTreeList(linkappArea);
        }
    }

    @Override
    public List<SpaceTreeVo> selectChildLinkappAreaTreeListByAreaPath(LinkappArea linkappArea) {
        LinkappArea la = new LinkappArea();
        la.setAreaPath(linkappArea.getAreaPath());

        List<SpaceTreeVo> stvList = selectLinkappAreaTreeList(la);
        if(org.apache.commons.lang3.ObjectUtils.isEmpty(stvList)){
            return null;
        }
        //所查询区域的下一级子区域
        List<SpaceTreeVo> linkappAreasNew = new ArrayList<>();
        for (SpaceTreeVo stv:
                stvList) {
            if(stv.getParentId() != null && stv.getParentId().equals(linkappArea.getId())){
                linkappAreasNew.add(stv);
            }
        }
        return linkappAreasNew;
    }

    @Override
    public Map<String, List<String>> getAreaRefDeviceCodeData(LinkappArea linkappArea) {
        LinkappArea la = new LinkappArea();
        la.setAreaPath(linkappArea.getAreaPath());
        LinkappArea linkappArea1 = selectLinkappArea(la);
        Assert.notNull(linkappArea1, "无此区域");

        //所查询区域的下一级子区域
        List<SpaceTreeVo> linkappAreasNew = selectChildLinkappAreaTreeListByAreaPath(linkappArea1);

        //循环查询区域下的所有设备
        Map<String, List<String>> areaDeviceCodeMap = new LinkedHashMap<>();
        if(org.apache.commons.lang3.ObjectUtils.isEmpty(linkappAreasNew)){
            List<Device> deviceList = getDeviceList(linkappArea1.getId());
            if(org.apache.commons.lang3.ObjectUtils.isEmpty(deviceList)){
                areaDeviceCodeMap.put(linkappArea1.getAreaName(), null);
            }else {
                List<String> collect = deviceList.stream().map(Device::getCode).collect(Collectors.toList());
                areaDeviceCodeMap.put(linkappArea1.getAreaName(), collect);
            }
        }else {
            for (SpaceTreeVo stv2:
                    linkappAreasNew) {
                List<Device> deviceList = getDeviceList(stv2.getId());
                if(org.apache.commons.lang3.ObjectUtils.isEmpty(deviceList)){
                    areaDeviceCodeMap.put(stv2.getName(), null);
                }else {
                    List<String> collect = deviceList.stream().map(Device::getCode).collect(Collectors.toList());
                    areaDeviceCodeMap.put(stv2.getName(), collect);
                }
            }
        }
        return areaDeviceCodeMap;
    }

    @Override
    public Map<String, List<String>> getSpaceRefDeviceCodeData() {
        List<LinkappSpace> linkappSpaceList = linkappSpaceService.selectLinkappSpaceList(null);

        //循环查询空间下的所有设备
        Map<String, List<String>> spaceDeviceCodeMap = new LinkedHashMap<>();
        if(!org.apache.commons.lang3.ObjectUtils.isEmpty(linkappSpaceList)){
            for (LinkappSpace linkappSpace:
                    linkappSpaceList) {
                List<Device> deviceList = getDeviceList(linkappSpace.getId());
                if(org.apache.commons.lang3.ObjectUtils.isEmpty(deviceList)){
                    spaceDeviceCodeMap.put(linkappSpace.getSpaceName(), null);
                }else {
                    List<String> collect = deviceList.stream().map(Device::getCode).collect(Collectors.toList());
                    spaceDeviceCodeMap.put(linkappSpace.getSpaceName(), collect);
                }
            }
        }
        return spaceDeviceCodeMap;
    }

    private List<Device> getDeviceList(String areaId){
        QueryWrapper qw = new QueryWrapper();
        qw.eq("delete_state", 1);
        qw.eq("area_id", areaId);
        List<Device> list = deviceMapper.selectList(qw);
        return list;
    }

    @Override
    public List<LinkappArea> selectLinkappAreaLowLevlNodeList(LinkappArea linkappArea) {
        return linkappAreaMapper.selectLinkappAreaLowLevlNodeList(linkappArea);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Set importData(MultipartFile file,LinkappSpace space) {
        Set deviceErrorList = new HashSet();
        List<LinkappArea> areas = getImportData(getContentList(file), deviceErrorList,space);
        return deviceErrorList;
    }

    private List<List<String>> getContentList(MultipartFile file) {

        List<List<String>> contentList = ExcelReadUtil
            .getExcelInfo(file, 2, null, -1);

        //验证导入文件 是否使用了正确的模板，以及表格第一列是否缺失或多了字段
        Map<Integer, String> standardHeaderRow = new HashMap<>(4);

        String keyValue = "空间名称(辅助):spaceName,一级区域名称(必填):firstName,二级区域名称(选填):secondName,三级区域名称(选填):thirdName";
        List<String> keys = Arrays.asList(StringUtils.split(keyValue, ",")).stream().map(s -> s = s.substring(0, s.indexOf(":"))).collect(Collectors.toList());
        for (int i = 0; i < keys.size(); i++) {
            standardHeaderRow.put(i, keys.get(i));
        }

        StringUtils.split(",");
        //根据表头判断是否使用了正确的模板
        //ExcelReadUtil.validateExeclTemplet(contentList, 1, standardHeaderRow);

        int[] requiredColumnIndexes = {1};

        int errorNum = ExcelReadUtil.validateRequiredFields(contentList, requiredColumnIndexes);
        if (errorNum != -1) {
            throw new RuntimeException("第" + (errorNum + 1) + "行,必填写列为空");
        }
        return contentList;
    }


    private List<LinkappArea> getImportData(List<List<String>> contentList, Set deviceErrorList,LinkappSpace space) {
    	LinkappArea firstArea;
    	LinkappArea secondArea;
    	LinkappArea thirdArea;
        String value;
        space = linkappSpaceMapper.selectLinkappSpace(space);
        List<LinkappArea> areas = new ArrayList<>();
        LinkappUser user = linkappUserContextProducer.getCurrent();
        for (int row = 0; row < contentList.size(); row++) {
            try {
                boolean loop = true;
                List<LinkappArea> areaList = new ArrayList<LinkappArea>();
                firstArea = new LinkappArea();
                secondArea = new LinkappArea();
                thirdArea = new LinkappArea();
                for (int i = 0; i < contentList.get(row).size() && loop; i++) {
                    value = StringUtils.isEmpty(contentList.get(row).get(i))
                        || StringUtils.isEmpty(contentList.get(row).get(i).trim())
                        ? null : contentList.get(row).get(i).trim();
                    switch (i) {
                        case 0:
//                        	space.setSpaceName(value);
//                            space = linkappSpaceMapper.selectLinkappSpace(space);
                            if (space==null) {
                            	 deviceErrorList.add(row + 3);
                            	 loop = false;
                            }
                            break;
                        case 1:
                            if (null != value &&  space!=null) {
                            	firstArea = new LinkappArea();
                            	firstArea.setSpaceId(space.getId());
                            	firstArea.setAreaName(value);
                                areaList = linkappAreaMapper.selectLinkappAreaList(firstArea);
                                if (areaList.isEmpty()) {
                                	firstArea.setSpaceId(space.getId());
                                	firstArea.setParentId(space.getId());
                                	firstArea.setAreaPath(space.getSpaceName() + ":" + value);
                                	firstArea = this.test(firstArea);
                                	firstArea.setTenantId(user.getTenantId());
                                	firstArea.setCreateTime(new Date());
                                	String sortNo = row + "" + i;
                                	firstArea.setSortNo(Integer.valueOf(sortNo));
                                	linkappAreaMapper.insert(firstArea);
                                	deviceErrorList.remove(row + 3);
                                }else {
                                	firstArea = areaList.get(0);
                                	deviceErrorList.add(row + 3);
                                }
                            }
                            break;
                        case 2:
                            if (null != value && space!=null) {
                            	secondArea.setAreaName(value);
                            	secondArea.setParentId(firstArea.getId());
                            	secondArea.setSpaceId(space.getId());
                                areaList = linkappAreaMapper.selectLinkappAreaList(secondArea);
                                if (areaList.isEmpty()) {
                                	secondArea.setSpaceId(space.getId());
                                	secondArea.setParentId(firstArea.getId());
                                	secondArea.setAreaPath(firstArea.getAreaPath() + ":" + value);
                                	secondArea = this.test(secondArea);
                                	secondArea.setTenantId(user.getTenantId());
                                	secondArea.setCreateTime(new Date());
                                	String sortNo = row + "" + i;
                                	secondArea.setSortNo(Integer.valueOf(sortNo));
                                	linkappAreaMapper.insert(secondArea);
                                	deviceErrorList.remove(row + 3);
                                }else {
                                	secondArea = areaList.get(0);
                                	deviceErrorList.add(row + 3);
                                }
                            }
                            break;
                        case 3:
                            if (null != value && space!=null) {
                            	thirdArea = new LinkappArea();
                            	thirdArea.setParentId(secondArea.getId());
                            	thirdArea.setSpaceId(space.getId());
                            	thirdArea.setAreaName(value);
                            	areaList = linkappAreaMapper.selectLinkappAreaList(thirdArea);
                                if (areaList.isEmpty()) {
                                	thirdArea.setSpaceId(space.getId());
                                	thirdArea.setParentId(secondArea.getId());
                                	thirdArea.setAreaPath(secondArea.getAreaPath() + ":" + value);
                                	thirdArea = this.test(thirdArea);
                                	thirdArea.setTenantId(user.getTenantId());
                                	thirdArea.setCreateTime(new Date());
                                	String sortNo = row + "" + i;
                                	thirdArea.setSortNo(Integer.valueOf(sortNo));
                                	linkappAreaMapper.insert(thirdArea);
                                	deviceErrorList.remove(row + 3);
                                }else{
                                	deviceErrorList.add(row + 3);
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
            } catch (Exception e) {
                deviceErrorList.add(row + 3);
                continue;
            }
        }
        return areas;
    }



    public  LinkappArea test(LinkappArea linkappArea) {
    	LinkappArea linkappAreaQuery = new LinkappArea();
        linkappAreaQuery.setAreaName(linkappArea.getAreaName());
        linkappAreaQuery.setParentId(linkappArea.getParentId());
        List<LinkappArea> listQuery = linkappAreaMapper.selectLinkappAreaList(linkappAreaQuery);
        if (listQuery.size() == 0) {
            //区域编码生成规则
            linkappAreaQuery = new LinkappArea();
            linkappAreaQuery.setParentId(linkappArea.getParentId());
            linkappAreaQuery.setStatus("1");
            List<LinkappArea> list = linkappAreaMapper.selectLinkappAreaList(linkappAreaQuery);
            linkappAreaQuery = new LinkappArea();
            linkappAreaQuery.setId(linkappArea.getParentId());
            List<LinkappArea> queryList = linkappAreaMapper.selectLinkappArea(linkappAreaQuery);
            linkappAreaQuery = queryList.size() > 0 ? queryList.get(0) : null;
            Integer count = list.size();
            String areaNo = String.format("%3d", count + 1).replace(" ", "0");
            String parentAreaNo = "";
            if (linkappAreaQuery != null && linkappAreaQuery.getAreaNo() != null && linkappAreaQuery.getAreaNo().length() > 0) {
                parentAreaNo = linkappAreaQuery.getAreaNo();
            }
            linkappArea.setAreaNo(parentAreaNo + areaNo);
            return linkappArea;
        }
    	return null;
    }



    @Override
    public void getImportTemplate(HttpServletRequest request, HttpServletResponse response) {
        String title = "区域批量导入模板";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                .getOutputStream(request, response, fileName);

            String keyValue = "空间名称(辅助):spaceName,一级区域名称(必填):firstName,二级区域名称(选填):secondName,三级区域名称(选填):thirdName";
            ExcelTools
                .exportExcel(outputStream, keyValue,new AreaExportModel().inits(), ExcelConstant.XLS,
                    title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            LOGGER.error("excel导出失败",e);
            throw new RuntimeException("excel导出失败！IOException异常");
        } catch (Exception e) {
            LOGGER.error("excel导出失败",e);
            throw new RuntimeException("excel导出失败！");
        }

    }

    @Override
    public void exportData(LinkappArea area, HttpServletRequest request, HttpServletResponse response) {

        List<LinkappArea> result = linkappAreaMapper.selectExportLinkappAreaList(area);
        List<HashMap<String, Object>> resultSimple = null;
        String keyValue = "区域名称:areaName,区域 编号:areaNo,上级区域名称:parentName,上级区域 编号:parentNo,区域路径:areaPath,排序:sortNo,位置详情:site,备注:remark";
        String title = "空间区域表";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, result, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            LOGGER.error("excel导出失败",e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            LOGGER.error("excel导出失败",e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }

    }

    public String getCurrentUser() throws Exception {
        LinkappUser current = linkappUserContextProducer.getCurrent();
        if(current == null || org.thymeleaf.util.StringUtils.isEmpty(current.getTenantId())){
            throw new Exception("未获取到当前用户信息");
        }
        return current.getTenantId();
    }



    @Override
    public void bindTenantAndAreaPath(DeviceVoExt adp){
        try{
            if(adp.getSpaceTreeVos() != null && !adp.getSpaceTreeVos().isEmpty()){
                String tenantId = getCurrentUser();
                List<TenantFunctionRefArea> tfraList = new ArrayList<TenantFunctionRefArea>();
                //先删除之前绑定的数据
                Map<String, Object> deleteMap = new HashMap<String, Object>();
                deleteMap.put("tenant_id", tenantId);
//                    deleteMap.put("area_id", stv.getId());
//                    deleteMap.put("area_path", stv.getAreaPath());
                deleteMap.put("function_identifier", adp.getFunctionIdentifier());
                tenantFunctionRefAreaMapper.deleteByMap(deleteMap);
                for (SpaceTreeVo stv:
                        adp.getSpaceTreeVos()) {
                    Assert.notNull(stv.getId(), "区域id不能为空");
                    Assert.notNull(stv.getAreaPath(), "区域路径不能为空");

                    //重新绑定
                    TenantFunctionRefArea tfra = new TenantFunctionRefArea();
                    tfra.setTenantId(tenantId);
                    tfra.setAreaId(stv.getId());
                    tfra.setAreaPath(stv.getAreaPath());
                    tfra.setFunctionIdentifier(adp.getFunctionIdentifier());
                    tfraList.add(tfra);
                }
                tenantFunctionRefAreaMapper.batchInsert(tfraList);
            }
        }catch(Exception e){
            log.error(e.getMessage());
        }
    }

    @Override
    public List<SpaceTreeVo> getAreaTreeListByFunctionIdentifier(TenantFunctionRefArea tfra) {
        try{
            String tenantId = getCurrentUser();
            tfra.setTenantId(tenantId);
            tfra.setFunctionIdentifier(tfra.getFunctionIdentifier());
            List<SpaceTreeVo> areaTreeListByFunctionIdentifier = baseMapper.getAreaTreeListByFunctionIdentifier(tfra);
            return areaTreeListByFunctionIdentifier;
        }catch(Exception e){
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 视频监控-树形结构(包含设备)
     */
    @Override
    public List<SpaceTreeVo> selectAreaTreeListWithDevice(LinkappArea linkappArea) {
        List<SpaceTreeVo> list = selectLinkappAreaTreeList(linkappArea);
        // 按 parentId 组装成一棵树
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        //查询设备
        IPage<DeviceVideoMonitorVo> page = videoMonitorService.page(new Page<>(1, -1), new Device());
        List<DeviceVideoMonitorVo> records = page.getRecords();
//        records.forEach(r->{
//            //将AreaPath中的/替换成:
//            r.setAreaPath(r.getAreaPath().replaceAll("/", ":"));
//        });
        list.forEach(spaceTreeVo -> {
            spaceTreeVo.setVideoDeviceList(records.stream()
                    .filter(device -> spaceTreeVo.getAreaPath().equals(device.getAreaPath())
                    || spaceTreeVo.getAreaPath().replaceAll(":", "/").equals(device.getAreaPath().replaceAll(":", "/"))
                    )
                    .collect(Collectors.toList()));
        });
        // 配置树节点
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setParentIdKey("parentId");
        treeNodeConfig.setNameKey("name");
        treeNodeConfig.setWeightKey("sortNo");

        // 构建树形结构，根节点的parentId为null或空字符串
        List<Tree<String>> treeList = TreeUtil.build(list, null, treeNodeConfig, (treeNode, tree) -> {
            tree.setId(treeNode.getId());
            tree.setParentId(treeNode.getParentId());
            tree.setName(treeNode.getName());
            tree.setWeight(treeNode.getSortNo());
            tree.putExtra("spaceTreeVo", treeNode);
        });

        // 将Tree结构转换回SpaceTreeVo结构
        return convertTreeToSpaceTreeVo(treeList);
    }

    /**
     * 将Tree结构转换为SpaceTreeVo结构
     */
    private List<SpaceTreeVo> convertTreeToSpaceTreeVo(List<Tree<String>> treeList) {
        List<SpaceTreeVo> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(treeList)) {
            return result;
        }

        for (Tree<String> tree : treeList) {
            SpaceTreeVo spaceTreeVo = (SpaceTreeVo) tree.get("spaceTreeVo");
            if (spaceTreeVo != null) {
                // 递归处理子节点
                List<Tree<String>> children = tree.getChildren();
                if (CollectionUtil.isNotEmpty(children)) {
                    spaceTreeVo.setChildren(convertTreeToSpaceTreeVo(children));
                } else {
                    spaceTreeVo.setChildren(new ArrayList<>());
                }
                result.add(spaceTreeVo);
            }
        }
        return result;
    }

    @Data
     public class AreaExportModel{
        private String spaceName;
        private String firstName;
        private String secondName;
        private String thirdName;

        public  List<AreaExportModel> inits(){
            AreaExportModel areaExportModel = new AreaExportModel();
            areaExportModel.setSpaceName("光谷步行街");
            areaExportModel.setFirstName("西班牙风情街");
            areaExportModel.setSecondName("A区");
            areaExportModel.setThirdName("保利国际");
            return Arrays.asList(areaExportModel);
        }
    }

}
